/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ARF_MANAGER_H
#define ARF_MANAGER_H

#include <vector>
#include <map>
#include <string>

#include "access_rule_cache.h"
#include "secure_element_agent.h"
#include "device_appid_ref_do.h"
#include "aid_ref_do.h"
#include "channel_impl.h"
#include "ref_do.h"
#include "ar_do.h"
#include "ref_ar_do.h"
#include "apdu_ar_do.h"
#include "ef_ac_main.h"
#include "ef_ac_rules.h"

namespace OHOS {
namespace SE {
class ArfManager {
public:
    static ArfManager &GetInstance()
    {
        static ArfManager instance;
        return instance;
    }

    /**
     * @brief Initialize ARF rules
     * @param seAgent The agent used to access the secure element hardware
     * @return Is successfully initialized
     */
    bool Initialize(std::weak_ptr<SecureElementAgent> seAgent);

    /**
     * @brief Transmit apdu to secure element hardware
     * @param efParser The current EF parser
     * @param cmd The command apdu to be transmitted
     * @return Response in vector
     */
    std::vector<uint8_t> TransmitArfApdu(std::shared_ptr<EfParser> efParser, const std::vector<uint8_t> &cmd);

    /**
     * @brief Add arf rule to current cule cache.
     * @param aidRefDo AID to access secure element
     * @param deviceAppIdRefDo App ID to access secure element
     * @param isAllowed Is access allowed by rule
     */
    void AddArfRule(
        std::shared_ptr<AidRefDo> aidRefDo, std::shared_ptr<DeviceAppIdRefDo> deviceAppIdRefDo, bool isAllowed);

    /**
     * @brief Get current arf rules in cache
     * @return All current arf rules
     */
    std::vector<std::shared_ptr<RefArDo>> GetArfRule();

    /**
     * @brief Clear all arf rules in cache
     */
    void ClearArfRules();

    /**
     * @brief Get name of se currently in use
     * @return Current se name
     */
    std::string GetUsedSeName();

    /**
     * @brief Set name of se currently in use
     * @param seName Current se name
     */
    void SetUsedSeName(const std::string &seName);

    /**
     * @brief Get refresh tag in se hardware
     * @param seName Current refresh tag
     */
    std::vector<uint8_t> GetRefreshTag();

    /**
     * @brief Set refresh tag
     * @param refreshTag Current refresh tag
     */
    void SetRefreshTag(const std::vector<uint8_t> &refreshTag);

private:
    ArfManager();
    ~ArfManager();

    // ARF initialization
    void GetEfAcMain();
    bool LoadArfRules();

    // Functions to operate channel
    void CloseArfChannel();
    bool OpenLogicalArfChannel(const std::vector<uint8_t> &aid);
    sptr<ChannelImpl> OpenLogicalArfChannelByAid(const std::vector<uint8_t> &aid);
    int32_t TransmitArfApduBySimIO(
        int fileId, const std::vector<uint8_t> &filePath, const std::vector<uint8_t> &cmd, std::string &rsp);

    // Build RefArDo by RefDo
    void AddArfRule(std::shared_ptr<RefDo> refDo, bool isAllowed);

    std::weak_ptr<SecureElementAgent> secureElementAgent_ {};
    sptr<ChannelImpl> arfChannel_ {};
    std::string usedSeName_ = SE_NAME_ESE;

    std::vector<uint8_t> refreshTag_ {};
    std::shared_ptr<EfAcMain> acMain_ = nullptr;
    std::shared_ptr<EfAcRules> acRules_ = nullptr;
    std::vector<uint8_t> odfFilePath_ {};
    std::vector<uint8_t> acMainPath_ {};
    std::vector<std::shared_ptr<RefArDo>> arfRuleVec_ {};
};
}  // namespace SE
}  // namespace OHOS
#endif // ARF_MANAGER_H